package cn.ly.jvm.loader.diffloader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.plaf.synth.SynthSeparatorUI;

public class MainTest {
	
	static final String rootDir = "E:\\newtest\\workspace\\JavaTest\\bin";
	
	public static void main(String[] args) throws Exception, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
		//System.out.println("Thread id : " + Thread.currentThread().getId());
		//Thread.sleep(600 * 1000);
		ClassLoader1 cl1 = new ClassLoader1(rootDir);
		Class clz = cl1.loadClass("cn.ly.jvm.loader.diffloader.HelloTest");
		Method sayHello = clz.getMethod("sayHello",null);
		sayHello.invoke(clz.newInstance());
		HelloTest hello = new HelloTest();
		System.out.println(hello.equals(clz.newInstance()));
		
		System.out.println("等待查看jvm情况...");
		Scanner sc = new Scanner(System.in);
		int flag = sc.nextInt();
		if(flag == 1){
			System.out.println("continue...");
		}
		
		System.out.println("等待卸载3秒钟，start...");
		/**
		 * 卸载一个class，需要三个条件：
		 * 1、这个class对应的对象必须都被gc回收了
		 * 2、这个class的类对象不能还有引用，包括反射的引用
		 * 3、加载这个class的classloader必须也被gc回收了
		 * 满足以上三个条件，这个class对象才能被gc回收，这样才能最终卸载一个class
		 */
		sayHello = null;
		clz = null;
		cl1 = null;
		
		System.gc();
		int i = 3;
		while(i > 0){
			System.out.print(i-- + "...");
			Thread.sleep(1000);
		}
		System.out.println("stop!");
		
		System.out.println("after gc ClassLoader1  ：" + cl1);
		System.out.println("after gc Class HelloTest ：" + clz);
		System.out.println("after gc Class Method sayHello ：" + clz);
		
		Thread.sleep(1000 * 60 * 10);
		
		/*ClassLoader1 cl2 = new ClassLoader1(rootDir);
		Class clz3 = cl2.getClass("cn.ly.jvm.loader.diffloader.HelloTest");
		System.out.println("after gc ClassLoader1 clz3 getClass HelloTest ：" + clz3);*/
		
		
		/*HelloTest ht = new HelloTest();
		ClassLoader2 cl2 = new ClassLoader2(rootDir);
		ThreadTest tt = new ThreadTest();
		tt.setHelloTest(ht);
		
		tt.setContextClassLoader(cl2);
		tt.start();*/
		
	}
}

class ThreadTest extends Thread{
	private ClassLoader c;
	
	private HelloTest ht;
	
	public ThreadTest(){
	} 
	
	public void setHelloTest(HelloTest ht){
		this.ht = ht;
	}
	
	public void run(){
		try {
			//调用不是同一个classloader的加载的类的对象
			ht.sayHello();
			
			this.c = this.getContextClassLoader();
			System.out.println("contextClassLoader : " + this.c);
			System.out.println("ThreadTest classloader : " + this.getClass().getClassLoader());
			Thread.sleep(1000*5);
			Class clz = c.loadClass("cn.ly.jvm.loader.diffloader.HelloTest");
			Method sayHello = clz.getMethod("sayHello",null);
			sayHello.invoke(clz.newInstance(),null);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


/*Timer timerOut = new Timer();
timerOut.schedule(new TimerTask(){
	private int i = 3;
	public void run() {
		if(i == 0){
			timerOut.cancel();
		}
		System.out.print(i--);
	}
},0,1000);*/
